﻿using System.ComponentModel;
using System.Drawing;
using System.Drawing.Printing;
using System.Windows.Forms;
using NGridDrawer.Draw;
using NGridDrawer.Partitions;

namespace NGridDrawer.Components
{
    /// <LastUpdate author="Blaise Braye" Date="15/06/2008 20:27"/>
    /// <summary>
    /// Provide a user friendly interface to manage a data grid printing work flow
    /// </summary>
    [ToolboxBitmap(typeof (PrintDocument), "PrintDocument.bmp")]
    public abstract class DataGridViewAbstractDrawerComponent :
        Component, IPropertiesDrawer, IDrawerComponent
    {
        private DataGridView _dataGridView;

        private bool _mustCenterHorizontally;
        private bool _mustCenterVertically;
        private bool _mustFitColumnsToBounds;
        
        private bool _mustPrintSelectedColumns;
        private bool _mustPrintSelectedRows;

        private bool _mustPrintColumnHeaders;
        private bool _mustPrintRowHeaders;
        private PartitionOrder _printOrder;


        /// <summary>
        /// 	<para>Initializes an instance of the <see cref="DataGridViewAbstractDrawerComponent"/> class.</para>
        /// </summary>
        protected DataGridViewAbstractDrawerComponent()
        {
            InitializeComponent();
            PropertyChanged += dataGridViewAbstractDrawerComponent_PropertyChanged;
        }


        /// <summary>Get Component Property</summary>
        [Browsable(false)]
        public DataGridViewAbstractDrawer Drawer { get; private set; }

        /// <summary>Get/Set DataGridView Property</summary>
        public DataGridView DataGridView
        {
            get { return _dataGridView; }
            set
            {
                _dataGridView = value;
                OnPropertyChanged("DataGridView");
            }
        }

        #region IDrawerComponent Members

        /// <summary>Get/Set Component Property - Not implemented</summary>
        [Browsable(false)]
        public IDrawerComponent Component
        {
            get { return null; }
            set { }
        }

        /// <summary>Get IComponentDrawer.Component Property</summary>
        [Browsable(false)]
        IPartitionDrawer IDrawerComponent.Drawer
        {
            get { return Drawer; }
        }

        /// <summary>
        /// Occurs when a property value has changed
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region IPropertiesDrawer Members

        /// <summary>
        /// Defines if partitions must be horizontally centered in their bounds when painted
        /// </summary>
        public bool MustCenterHorizontally
        {
            get { return _mustCenterHorizontally; }
            set
            {
                _mustCenterHorizontally = value;
                OnPropertyChanged("MustCenterHorizontally");
            }
        }


        /// <summary>
        /// Defines if partitions must be vertically centered in their bounds when painted
        /// </summary>
        public bool MustCenterVertically
        {
            get { return _mustCenterVertically; }
            set
            {
                _mustCenterVertically = value;
                OnPropertyChanged("MustCenterVertically");
            }
        }


        /// <summary>
        /// Defines if proposed sizes must be scaled in order to fit whole of columns on a single partition
        /// </summary>
        public bool MustFitColumnsToBounds
        {
            get { return _mustFitColumnsToBounds; }
            set
            {
                _mustFitColumnsToBounds = value;
                OnPropertyChanged("MustFitColumnsToBounds");
            }
        }


        /// <summary>
        /// Defines if only selected columns must be printed
        /// </summary>
        public bool MustPrintSelectedColumns
        {
            get { return _mustPrintSelectedColumns; }
            set
            {
                _mustPrintSelectedColumns = value;
                OnPropertyChanged("MustPrintSelectedColumns");
            }
        }


        /// <summary>
        /// Defines if only selected rows must be printed
        /// </summary>
        public bool MustPrintSelectedRows
        {
            get { return _mustPrintSelectedRows; }
            set
            {
                _mustPrintSelectedRows = value;
                OnPropertyChanged("MustPrintSelectedRows");
            }
        }


        /// <summary>
        /// Defines if column headers must be printed
        /// </summary>
        public bool MustPrintColumnHeaders
        {
            get { return _mustPrintColumnHeaders; }
            set
            {
                _mustPrintColumnHeaders = value;
                OnPropertyChanged("MustPrintColumnHeaders");
            }
        }

        /// <summary>
        /// Defines if row headers must be printed
        /// </summary>
        public bool MustPrintRowHeaders
        {
            get { return _mustPrintRowHeaders; }
            set
            {
                _mustPrintRowHeaders = value;
                OnPropertyChanged("MustPrintRowHeaders");
            }
        }

        


        /// <summary>
        /// Defines in which order partitions must be painted
        /// </summary>
        public PartitionOrder PrintOrder
        {
            get { return _printOrder; }
            set
            {
                _printOrder = value;
                OnPropertyChanged("PrintOrder");
            }
        }

        #endregion

        /// <summary>
        /// initialize a <see cref="DataGridViewAbstractDrawer"/> object
        /// </summary>
        /// <param name="gridView">Grid of data which must be drawn
        /// </param>
        /// <returns>
        /// <see cref="DataGridViewAbstractDrawer"/> object initialized
        /// </returns>
        protected abstract DataGridViewAbstractDrawer InitializeController(DataGridView gridView);


        /// <summary>
        /// State machine : a property has been modified, what to do?
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dataGridViewAbstractDrawerComponent_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName.Equals("DataGridView"))
            {
                // then init a drawer
                if (DataGridView != null)
                {
                    Drawer = InitializeController(DataGridView);
                    PropHelper.MovePropertiesTo<IPropertiesDrawer>(this, Drawer);
                }
                else Drawer = null;

                OnPropertyChanged("Drawer");
            }

            if (Drawer != null && PropHelper.ContainsProp<IPropertiesDrawer>(this, e.PropertyName))
            {
                // update the drawer property
                PropHelper.CopyProperty<IPropertiesDrawer>(this, Drawer, e.PropertyName);
            }
        }

        /// <summary>
        /// <see cref="INotifyPropertyChanged"/> implementation
        /// </summary>
        /// <param name="propertyName">name of the property which has a changed value
        /// </param>
        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        #region Component Design

        private IContainer _components;

        /// <summary>
        /// 	<para>Initializes an instance of the <see cref="DataGridViewAbstractDrawerComponent"/> class.</para>
        /// </summary>
        /// <param name="container">
        /// </param>
        protected DataGridViewAbstractDrawerComponent(IContainer container)
        {
            container.Add(this);
            InitializeComponent();

            if (!DesignMode)
                PropertyChanged += dataGridViewAbstractDrawerComponent_PropertyChanged;
        }

        /// <summary>Get/Set Components Property</summary>
        protected IContainer Components
        {
            get { return _components; }
            set { _components = value; }
        }

        /// <summary> 
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (Components != null))
            {
                _components.Dispose();
            }
            base.Dispose(disposing);
        }


        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        protected void InitializeComponent()
        {
            _components = new Container();
        }

        #endregion Component Design
    }
}